package stack;

import org.junit.Test;

import java.util.Stack;

public class InfixExpression {
    @Test
    public void test(){
//        Util util = new Util();
//        ArrayStack stack = new ArrayStack(10);
//        System.out.println(stack.getPriority("*"));
//        System.out.println(stack.getPriority("/"));
//        System.out.println(stack.getPriority("-"));
//        System.out.println(stack.getPriority("+"));

         calExpression("1+2*3-4");
    }
    public void calExpression(String expression){
        int index=0;
        String currentchar;//当前字符
        String topOper;//栈顶运算符
        int num1;//弹出的第一个运算数
        int num2;//弹出的第二个运算数
        String operchar;//弹出的操作符
        int calResult;//整体表达式计算结果

        Util util = new Util();
        ArrayStack numStack = new ArrayStack(29);
        Stack<String> operStack = new Stack<>();


        while(true){
            //读取字符,
            currentchar=expression.substring(index,index+1);
            //如果是数字
            if(util.isOper(currentchar)){
                //是操作符
                //如果栈为空,直接入栈,
                if (operStack.isEmpty()){
                    //操作符且栈为空直接入站
                    operStack.push(currentchar);
                }else{
                    //栈不为空,需要判断当前操作符与栈顶操作符之间的优先级关系
                    topOper=operStack.peek();
                    if (numStack.getPriority(topOper)>=numStack.getPriority(currentchar)){
                        //如果当前字符的优先级小于栈顶字符,则需要弹出相应的数字和运算符进行计算
                        num1=numStack.pop();
                        num2=numStack.pop();
                        operchar=operStack.pop();
                        int res = util.cal(num1, num2, operchar);
                        //将计算结果压入栈,并将当前所扫描到的运算符添加到栈中
                        numStack.push(res);
                        operStack.push(currentchar);
                    }else{
                        //当前运算符的优先级大于栈顶字符的优先级,则将当前运算符压入栈中
                        operStack.push(currentchar);
                    }
                }
                index++;

            }else{
                //当前扫描到的是数字
                  //扫描到数子时不能直接进栈,必须读取完整数据
                String keepnum="";
                String t = currentchar;
                while(!util.isOper(t)){
                      //继续读取到的下一位仍然是数字,就将数字拼入字符串
                      index++;
                      keepnum+=t;
                      if (index==expression.length())
                          break;
                      t = expression.substring(index, index+ 1);
                      //进行拼接
                  }
                      numStack.push(Integer.parseInt(keepnum));
                      keepnum="";
            }
            //当前字符处理完毕

            if (index>=expression.length()){
                break;
            }
            System.out.println("-------开头-----------");
            System.out.println("数字栈:");
            numStack.travelStack();
            System.out.println("运算符栈");
            operStack.forEach(i-> System.out.println(i));
            System.out.println("--------结尾----------");
        }
          while(!operStack.isEmpty()){
              num1=numStack.pop();
              num2=numStack.pop();
              operchar=operStack.pop();
              int res = util.cal(num1, num2, operchar);
              numStack.push(res);
          }
          //所有工作进行完毕,取出数字栈底元素
        calResult=numStack.pop();
        System.out.printf("%s=%d",expression,calResult);
    }
}
class Util{
    //需要提供计算方法,是否是字符
    public int cal(int num1,int num2,String oper){
        switch(oper){
            case "+":return num1+num2;
            case "-":return num2-num1;
            case "*":return num1*num2;
            case "/":return num2/num1;
            default:return -1;
        }
    }
    public Boolean isOper(String oper){
        return oper.equals("+")||oper.equals("-")||oper.equals("*")||oper.equals("/");

    }
}
class ArrayStack{
    private  int top=-1;
    private int maxSize;
    private static int[] stack;
    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        stack=new int[maxSize];
    }
    public int getTopValue() {
        return top;
    }
    public int pop(){
        if (top==-1){
            System.out.println("栈空,无法出栈");
            return -1;
        }
        return stack[top--];
    }
    public void push(int data){
        if (top>=maxSize){
            System.out.println("栈满,无法入栈");
            return;
        }
        stack[++top]=data;
    }
    public boolean isEmpty(){
        if (top==-1)
            return true;
        return false;
    }
    public int peek(){
        //不出站,查看栈顶元素
        return stack[top];
    }
    public int getPriority(String currentChar){
        //当前环境下默认只有加减乘除运算
        if (currentChar.equals("*")|| currentChar.equals("/"))
            return 1;
        else
            return 0;
    }
    public void travelStack(){
        for (int i = 0; i <=top; i++) {
            System.out.print(stack[i]+"   ");
        }
        System.out.println();
    }

}